package hu.bme.aut.consulttime.server.entityservices;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.TypedQuery;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import hu.bme.aut.consulttime.client.LogService;
import hu.bme.aut.consulttime.entitydtos.LogDTO;
import hu.bme.aut.consulttime.server.email.EmailProvider;
import hu.bme.aut.consulttime.server.entities.Log;
import hu.bme.aut.consulttime.server.entities.ToDo;

public class LogServiceImpl extends RemoteServiceServlet implements LogService {

	private static final long serialVersionUID = -3175241236005847109L;

	public static final EntityManager entityManager() {
		return EntityManagerFactoryWrapper.get().createEntityManager();
	}
	
	@Override
	public long createLog(LogDTO logDTO) {

		EntityManager em = entityManager();
		EntityTransaction tx = em.getTransaction();

		Log log = new Log();
		log.setLogId(logDTO.getLogId());
		log.setDate(logDTO.getDate());
		log.setDescription(logDTO.getDescription());
		log.setAttachedFileName(logDTO.getAttachedFileName());
		log.setWorkHour(logDTO.getWorkHour());

		try {
			tx.begin();
			log.setToDo(em.find(ToDo.class, logDTO.getToDoId()));
			em.persist(log);
			tx.commit();
		} 
		catch (Throwable t) {
			t.printStackTrace();
			tx.rollback();
		} 
		finally {
			em.close();
		}
		
		try {
			
			if (log.getToDo().getTutor().isEmailNotification()) {
				
				String emailAddress = log.getToDo().getTutor().getEmail();
				String subject = "New log on ConsultTime!";
				String body = "Project: " + log.getToDo().getTeam().getProject().getTitle() + "\n";
				body = body + "Team: " + log.getToDo().getTeam().getName() + "\n";
				body = body + "Student: " + log.getToDo().getStudent().getFirstName() + " " + log.getToDo().getStudent().getLastName() + " (" + log.getToDo().getStudent().getUserName() + ")\n\n";
				body = body + "To-do:\n";
				body = body + "Date: " + log.getToDo().getDate().toString() + "\n";
				body = body + "Title: " + log.getToDo().getTitle() + "\n";
				body = body + "Week: " + String.valueOf(log.getToDo().getWeek()) + "\n\n";
				body = body + "Log:\n";
				body = body + "Date: " + log.getDate().toString() + "\n";
				body = body + "Work hours: " + String.valueOf(log.getWorkHour()) + "\n\n";
				body = body + log.getDescription();
				
				EmailProvider.sendEmail(emailAddress, subject, body);
			}
		} catch (Throwable t) {
			t.printStackTrace();
		}		
		
		return logDTO.getToDoId();
	}
	
	@Override
	public LogDTO retrieveLog(long logId) {

		EntityManager em = entityManager();
		Log log = null;

		try {
			log = em.find(Log.class, logId);
		}
		catch (Throwable t) {
			t.printStackTrace();
		}
		finally {
			em.close();
		}

		return createLogDTO(log);
	}    
	
	@Override
	public List<LogDTO> retrieveLogs(long toDoId) {

		EntityManager em = entityManager();
		List<Log> logs = null; 

		try {			
			TypedQuery<Log> query = em.createQuery("select l from Log l where l.toDo.todoId = ?1", Log.class);
			query.setParameter(1, toDoId);
			logs = query.getResultList();
		}
		catch (Throwable t) {
			t.printStackTrace();
		}
		finally {
			em.close();
		}
		
		List<LogDTO> logDTOs = new ArrayList<LogDTO>(logs != null ? logs.size() : 0);
	    if (logs != null) {
	      for (Log log : logs) {
	        logDTOs.add(createLogDTO(log));
	      }
	    }
		
		return logDTOs;
	}
	
	@Override
	public long updateLog(LogDTO logDTO) {

		EntityManager em = entityManager();
		EntityTransaction tx = em.getTransaction();

		Log log = new Log();
		log.setLogId(logDTO.getLogId());
		log.setDate(logDTO.getDate());
		log.setDescription(logDTO.getDescription());
		log.setAttachedFileName(logDTO.getAttachedFileName());
		log.setWorkHour(logDTO.getWorkHour());

		try {
			tx.begin();
			log.setToDo(em.find(ToDo.class, logDTO.getToDoId()));

			em.merge(log);

			tx.commit();
		} 
		catch (Throwable t) {
			t.printStackTrace();
			tx.rollback();
		} 
		finally {
			em.close();
		}
		
		try {
			
			if (log.getToDo().getTutor().isEmailNotification()) {
				
				String emailAddress = log.getToDo().getTutor().getEmail();
				String subject = "Updated log on ConsultTime!";
				String body = "Project: " + log.getToDo().getTeam().getProject().getTitle() + "\n";
				body = body + "Team: " + log.getToDo().getTeam().getName() + "\n";
				body = body + "Student: " + log.getToDo().getStudent().getFirstName() + " " + log.getToDo().getStudent().getLastName() + " (" + log.getToDo().getStudent().getUserName() + ")\n\n";
				body = body + "To-do:\n";
				body = body + "Date: " + log.getToDo().getDate().toString() + "\n";
				body = body + "Title: " + log.getToDo().getTitle() + "\n";
				body = body + "Week: " + String.valueOf(log.getToDo().getWeek()) + "\n\n";
				body = body + "Log:\n";
				body = body + "Date: " + log.getDate().toString() + "\n";
				body = body + "Work hours: " + String.valueOf(log.getWorkHour()) + "\n\n";
				body = body + log.getDescription();
				
				EmailProvider.sendEmail(emailAddress, subject, body);
			}
		} catch (Throwable t) {
			t.printStackTrace();
		}
		
		return log.getToDo().getTodoId();
	}
	
	@Override
	public long deleteLog(long logId) {

		EntityManager em = entityManager();
		EntityTransaction tx = em.getTransaction();
		long toDoId = 0;

		try {
			tx.begin();
			Log log = em.find(Log.class, logId);
			toDoId = log.getToDo().getTodoId();
			em.remove(log);
			tx.commit();
		} 
		catch (Throwable t) {
			t.printStackTrace();
			tx.rollback();
		} 
		finally {
			em.close();
		}
		return toDoId;
	}

	private LogDTO createLogDTO(Log log) {
		return new LogDTO(log.getLogId(), log.getDate(), log.getDescription(), log.getAttachedFileName(), log.getWorkHour(), log.getToDo().getTodoId());
	}
}
